﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace ConsoleApplication
{
    /// <summary>
    //  Base Class
    /// </summary>
    public class BaseMathObjects : AbstractObjectClass, IObjects, ICloneable, IDisposable
    {
        protected int iCount;

        #region Constructor Methods Group

        public BaseMathObjects()
        {
            //Console.WriteLine("BaseMathObjects's default constructor - BaseMathObjects().");
        }
        public BaseMathObjects(string name)
        {
            //Console.WriteLine("BaseMathObjects's non-default constructor - BaseMathObjects(\"{0}\").", name);
        }

        #endregion

        #region Implement Interface Methods

        //  实现接口 - IDisposable 的 Dispose() 方法。
        public void Dispose()
        { }

        //  实现接口 - ICloneable 的 Clone() 方法。
        public object Clone()
        {
            BaseMathObjects object0 = new BaseMathObjects();
            return object0;
        }

        #endregion

        #region Property

        string name;
        new public string Name
        {
            get { return name; }
            set { name = value; }
        }

        #endregion

        #region BLL Methods

         public static void MainClassMethod()
        {
            CallShowNameMethod();
            //CallIsOnSameLineMethod();
            //polymorphic();
            //ShallowCopy();
            //DeepCopy();
            //ShowPointsCollection();
            //ShowPointsDictionary();
        }


       /// <summary>
        /// BLL, 赋值并调用ShowName方法
        /// </summary>
        static void CallShowNameMethod()
        {
            BaseMathObjects mObject = new BaseMathObjects();    //  先调用基类 AbstractObjectClass 的默认构造函数。
            mObject.Name = "BaseMathObjects_01";
            mObject.ShowName();     //      先调用基类 AbstractObjectClass 的ShowName()方法。
        }

        /// <summary>
        /// BLL, 赋值并调用IsOnSameLine方法
        /// </summary>
        static void CallIsOnSameLineMethod()
        {
            Point p1, p2, p3;
            p1 = new Point(0, 0);
            p2 = new Point(2, 2);
            p3 = new Point(2, 3);
            Console.WriteLine("The answer to whether the points: \np1({0}, {1}), p2({2}, {3}), p3({4}, {5}) are on the same line is: \n{6}.", p1.x.ToString(), p1.y.ToString(), p2.x.ToString(), p2.y.ToString(), p3.x.ToString(), p3.y.ToString(), IsOnSameLine(p1, p2, p3));
            Console.ReadKey();
        }

        #endregion

        #region Methods

        /// <summary>
        /// int 索引符示例，遍历 Points 对象
        /// </summary>
        public static void ShowPointsCollection()
        {
            PointsCollection pointCollection = new PointsCollection();
            pointCollection.Add(new Point("p1", 1, 1));
            pointCollection.Add(new Point("p2", 2, 2));

            Console.WriteLine("Using foreach to read each element of the Points.");
            foreach (Point p in pointCollection)    //      继承 CollectionBase 类的派生类可以使用 foreach。
            {
                Console.WriteLine(p.ToString());
            }
            Console.ReadKey(); Console.WriteLine();

            Console.WriteLine("Using Indexer to read each element of the Points.");
            for (int i = 0; i < pointCollection.Count; i++)     //      实现索引符 (indexer) 的类可以使用 Class[i] 的形式访问 项。
            {
                Console.WriteLine(pointCollection[i].ToString());
            }
            Console.ReadKey(); Console.WriteLine();

            Console.WriteLine("Using CopyTo() method copy from the new-Points-object to original-Points-object.");
            PointsCollection pointCollection_new = new PointsCollection();
            pointCollection_new.Add(new Point("p3", 3, 3));     //      NOTE: 1. MUST 初始化！
            //pointCollection_new.Add(new Point("p4", 4, 4));     //      2. 目标集合的元素个数一定要>=(可以小于)源集合。否则索引符的 index 都会报错越界。
            //pointCollection_new.Add(new Point("p5", 5, 5));

            //pointCollection.CopyTo(pointCollection_new);    //  CopyTo() method
            pointCollection_new.CopyTo(pointCollection);    //  CopyTo() method
            foreach (Point p in pointCollection)
            {
                Console.WriteLine(p.ToString());
            }
            Console.ReadKey();
        }

        /// <summary>
        /// string 索引符示例，遍历 Points 对象
        /// </summary>
        public static void ShowPointsDictionary()
        { 
            
        }

        #region Virtual Methods

        public void doSomething()
        {
            Console.WriteLine("Base doSomething.");
        }

        public virtual void doSomethingVirtual()
        {
            Console.WriteLine("Base virtual doSomething.");
        }

        #endregion

        #region Old Methods


        /// <summary>
        /// 类的多态示例
        /// </summary>
        static void polymorphic()
        {
            ///     多态
            AbstractObjectClass Object_A = new AbstractObjectClass();
            BaseMathObjects Object_B = new BaseMathObjects();

            //Object_A = Object_B;
            //Object_A = (BaseMathObjects)Object_A;

            //Object_B = (BaseMathObjects)Object_A;       //      Object_B = Object_A;    (*not work)

            Object_A.iCount = 10;
            Object_B.iCount = 10;
        }

        /// <summary>
        /// 对象的浅度复制示例
        /// </summary>
        static void ShallowCopy()
        {
            AbstractObjectClass Object_A = new AbstractObjectClass();
            BaseMathObjects Object_B = new BaseMathObjects();
            BaseMathObjects Object_BB = new BaseMathObjects();

            //     浅度复制
            object tempO = Object_B.MemberwiseClone();
            if (Object_BB.Equals(Object_B))
            {
                Console.WriteLine("{0} and \n{1} \nare equal.", Object_BB.ToString(), Object_B.ToString());
            }
            else
            {
                Console.WriteLine("{0} and \n{1} \nare NOT equal.", Object_BB.ToString(), Object_B.ToString());
            }
            Console.ReadKey();

            Object_B.Dispose();
        }

        /// <summary>
        /// 对象的深度复制示例
        /// </summary>
        static void DeepCopy()
        {
            AbstractObjectClass Object_A = new AbstractObjectClass();
            BaseMathObjects Object_B = new BaseMathObjects();

            //     深度复制
            BaseMathObjects tempO = (BaseMathObjects)Object_B.Clone();
            if (tempO.Equals(Object_B))
            {
                Console.WriteLine("{0} and \n{1} \nare equal.", tempO.ToString(), Object_B.ToString());
            }
            else
            {
                Console.WriteLine("{0} and \n{1} \nare NOT equal.", tempO.ToString(), Object_B.ToString());
            }
            Console.ReadKey();
        }


        /// <summary>
        /// 实现 IObjects 的 getName() 方法 (*必须)
        /// </summary>
        /// <returns></returns>
        public string getName()
        {
            return string.IsNullOrEmpty(Name) ? "Has no name yet.." : Name;
        }

        /// <summary>
        /// 显示本类型的name
        /// </summary>
        public override void ShowName()
        {
            base.ShowName("AbstractObjectClass_01");
            Console.WriteLine("BaseMathObjects's name is {0}.", getName());
            Console.ReadKey();
        }

        /// <summary>
        /// 求任意3点是否在一条直线上。k = tanα = ( y2 - y1 ) / ( x2 - x1 )
        /// </summary>
        static bool IsOnSameLine(Point p1, Point p2, Point p3)
        {
            bool result = false;
            float Kp1p2 = getGradient(p1, p2);
            float Kp2p3 = getGradient(p2, p3);
            float Kp1p3 = getGradient(p1, p3);

            if (Kp1p2 == Kp2p3)
            {
                if (Kp1p2 == Kp1p3)
                    result = true;
            }
            return result;
        }

        /// <summary>
        /// 求2点确定的一条直线的斜率。k = tanα = ( y2 - y1 ) / ( x2 - x1 )
        /// </summary>
        static float getGradient(Point p1, Point p2)
        {
            float Kp1p2;
            if (p1.x == p2.x || p1.y == p2.y)
            {
                Kp1p2 = 0;
            }
            else
            {
                Kp1p2 = Math.Abs((p2.y - p1.y) / (p2.x - p1.x));
            }

            return Kp1p2;
        }

        #endregion

        #endregion

    }

    /// <summary>
    ///  Child Class
    /// </summary>
    #region Math Object Classes

    public class Point : BaseMathObjects
    {
        #region Constructors
        
        //  Class Point's Constructors.
        //  NOTE:构造函数的执行序列。
        public Point()
            : base("I'm from BaseMathObjects")
        { }

        public Point(int x, int y)
            //: base("I'm from BaseMathObjects")
        {
            x_ = x;
            y_ = y;
        }

        public Point(string name, int x, int y)
        {
            Name = name;
            x_ = x;
            y_ = y;
        }


        #endregion

        #region Property
        
        int x_, y_;
        public int x
        {
            get { return x_; }
            set { x_ = value; }
        }

        public int y
        {
            get { return y_; }
            set { y_ = value; }
        }

        #endregion

        #region Methods
        
        //  隐藏基类 object.ToString() 方法。
        new public string ToString()
        {
            return string.Format("Point[\"{0}\"] x = {1}, y = {2}", base.Name, x, y);
        }

        //  隐藏基类 BaseMathObjects.doSomething() 方法。
        new public void doSomething()
        {
            Console.WriteLine("Point doSomething.");
        }

        //  重载基类 virtual BaseMathObjects.doSomething() 方法。
        public override void doSomethingVirtual()
        {
            base.doSomethingVirtual();
            Console.WriteLine("Point virtual doSomething.");
        }

        #endregion

        #region Operator Overload   +

        public static Point operator +(Point p1, Point p2)
        {
            return new Point(string.Format(@"new Point: {0} + {1}", p1.Name, p2.Name), p1.x + p2.x, p1.y + p2.y);
        }

        #endregion

        #region BLL Methods

        /// <summary>
        /// BLL, 调用doSomething方法
        /// </summary>
        new public static void MainClassMethod()
        {
            Point p = new Point();
            BaseMathObjects baseObj = p;
            
            //  #1
            p.doSomething();
            baseObj.doSomething();

            Console.ReadKey();

            //  #2
            p.doSomethingVirtual();
            baseObj.doSomethingVirtual();
            Console.ReadKey();
        }


        #endregion

    }

    /// <summary>
    /// 继承自 CollectionBase 类的 Points 集合
    /// </summary>
    public class PointsCollection : CollectionBase        //      CollectionBase, DictionaryBase
    {
        #region Contructors

        public PointsCollection()
        { }

        #endregion

        #region Methods

        public void Add(Point p)
        {
            List.Add(p);
        }

        public void Remove(Point p)
        {
            List.Remove(p);
        }

        public void CopyTo(PointsCollection targetPoints)
        {
            for (int index = 0; index < this.Count; index++)
            {
                targetPoints[index] = this[index];
            }
        }

        public bool Contains(Point p)
        {
            return InnerList.Contains(p); 
            //return List.Contains(p);    //  defferent with the 2?
        }

        #endregion

        #region Indexer

        //  索引符(indexer)
        public Point this[int PointIndex]
        {
            get
            {
                return (Point)List[PointIndex];
            }
            set
            {
                List[PointIndex] = value;
            }
        }

        //public IEnumerator GetEnumerator()
        //{

        //}


        #endregion
    }

    /// <summary>
    /// 继承自 DictionaryBase 类的 Points 集合
    /// </summary>
    public class PointsDictionary : DictionaryBase        //      CollectionBase, DictionaryBase
    {
        public PointsDictionary() { }

        public void Add(string key, Point p)
        {
            Dictionary.Add(key, p);
        }

        public void Remove(string key, Point p)
        {
            Dictionary.Remove(key);
        }

        /// <summary>
        /// 通过关键字访问的索引符
        /// </summary>
        /// <param name="pointID">关键字key</param>
        /// <returns></returns>
        public Point this[string pointID]
        {
            get 
            {
                return (Point)Dictionary[pointID];
            }

            set
            {
                Dictionary[pointID] = value;
            }
        }
    }

    #endregion


    #region Derived Class from Base Class
    

    /// <summary>
    /// Base Interface
    /// </summary>
    public interface IBaseInterface
    {
        string getPrivateString();
        string getProtectedString();
        string getPublicString();
    }
        
    /// <summary>
    ///  Base Class
    /// </summary>
    public class BaseClass : IBaseInterface
    {
        private string strPrivate = "strPrivateBase";
        protected string strProtected = "strProtectedBase";
        public string strPublic = "strPublicBase";
        public static string strPublicStatic = "strPublicStaticBase";

        private string getPrivateString()
        {
            return strPrivate;
        }
        protected string getProtectedString()
        {
            return strProtected;
        }

        string IBaseInterface.getPrivateString()
        {
            //throw new NotImplementedException();
            return strPrivate;
        }
        string IBaseInterface.getProtectedString()
        {
            //throw new NotImplementedException();
            return strProtected;
        }
        public string getPublicString()
        {
            //throw new NotImplementedException();
            return strPublic;
        }
        protected static string getstrPublicStatic()
        {
            return strPublicStatic;
        }
    }
    /// <summary>
    /// Derived Class from Base Class
    /// </summary>
    public class DerivedClass : BaseClass, IBaseInterface
    {
        private string strPrivate = "strPrivateDerived";
        new protected string strProtected = "strProtectedDerived";
        new public string strPublic = "strPublicDerived";

        string strTemp = BaseClass.strPublicStatic;

        public string DerivedClassMethod()
        {
            return this.strPrivate;
        }
        new public string getPublicString()
        {
            return strPublic;
        }
        public void main()
        {
            DerivedClass dc = new DerivedClass();
            dc.strProtected = "";
            dc.getProtectedString();

            this.strPrivate = "";
            this.getProtectedString();
            
            base.strProtected = "";
            base.getProtectedString();

            BaseClass.getstrPublicStatic();
            BaseClass.strPublicStatic = "";
            
        }
    }
    /// <summary>
    /// DerivedClass2 from Derived Class
    /// </summary>
    public class DerivedClass2 : DerivedClass
    {
        public void main2()
        {
            this.strProtected = "";
            this.getProtectedString();
        }
    }

    #endregion


    #region Structuer Objects

    public struct PointStruct
    {
        public int x, y;   //  x, y coordinate
    }

    //  线段
    struct LineSegment
    {
        PointStruct startPoint;   //  The start poin of the line segment.
        PointStruct EndPoint;   //  The end poin of the line segment.

        //  结构函数
        public int getLength()
        {
            return (EndPoint.x - startPoint.x) >= 0 ? (EndPoint.x - startPoint.x) : (startPoint.x - EndPoint.x);
        }
    }

    //  射线
    struct RadialStruct
    {
        PointStruct startPoint;
        int angle;      //  角度
    }

    //  直线
    struct LineStruct
    {
        //  any 2 points on the line.
        PointStruct Point1;
        PointStruct Point2;
    }

    #endregion

}
